<?php

namespace app\models\cacheModel;

use app\models\cache\AdminRole;
use app\models\CommonModel;
use app\models\tableModel\AdminRoleModel as AdminRoleDBModel;
use yii\helpers\ArrayHelper;

/**
 * 后台角色操作模型 缓存[Model]
 * User: jees
 * Date: 2020/09/10
 * Time: 15:09:06
 */
class AdminRoleModel extends AdminRole
{

    /**
     * 数据库实例
     * @var AdminRoleDBModel
     */
    protected $dbInstance;
    /**
     * 条件暂存
     * @var
     */
    protected $where;
    /**
     * 错误信息暂存
     * @var
     */
    private static $error_;

    public function __construct(array $config = [])
    {

        parent::__construct($config);
        // 先初始化下类
        $this->setDbInstance();
    }

    /**
     * 规则验证
     * @return array
     */
    public function rules()
    {

        return ArrayHelper::merge(parent::rules(), []);
    }

    /**
     * 字段属性
     * @return array
     */
    public function attributes()
    {

        return ArrayHelper::merge(parent::attributes(), [
            'needSave'
        ]);
    }

    /**
     * 场景
     * @return array
     */
    public function scenarios()
    {

        $scenarios = parent::scenarios();
        return ArrayHelper::merge($scenarios, [
            // 自定义场景 (无用请删除)
            'scUpdate' => [
                'someAttributes'
            ]
        ]);
    }

    /**
     * 加载整体[Model]
     * @param null $id 编号
     * @param string $scenario 场景
     * @return AdminRoleModel|\yii\redis\ActiveQuery|null
     */
    public static function loadModel($id = null, $scenario = 'default')
    {

        // 实力化类
        $model = new self();

        // ********** 1、查询缓存数据 **********
        // [id]是[true]返回
        if ($id === true) {
            return $model::find();
        } else if (!empty($id)) { // 有[id]去查询
            $model = $model::findOne($id);
        }

        // 不操作数据库 缓存查询的空
        if (empty($model)) return $model;

        // ********** 2、实例化场景 **********
        // 场景
        $sceList = array_keys($model->scenarios());
        if ($scenario && !empty($scenario) && in_array($scenario, $sceList)) {
            $model->setScenario($scenario);
        }

        return $model;
    }

    /**
     * 初始化[数据库]实例
     * @param bool $id 数据编号|直接初始化
     * @param string $scenario 场景|ps.缓存类场景
     * @return AdminRoleModel|AdminRoleDBModel|\yii\db\ActiveQuery|null
     */
    public static function loadModelDB($id = true, $scenario = 'default')
    {

        $model = new self();
        // ********** 1、查询缓存数据 **********
        // [id]是[true]返回
        if ($id === true) {
            $dbModel = AdminRoleDBModel::loadModel();
        } else if (!empty($id)) {
            $dbModel = AdminRoleDBModel::loadModel($id);
        }

        // 数据库查询的空 || id true 返回
        if (empty($dbModel)) return null;

        // 赋值数据库实例
        $model->setDbInstance($dbModel);

        // 需要把数据库[attribute]赋值到缓存
        $attribute = $dbModel->getAttributes();
        $model->setAttributes($attribute);

        // ********** 2、实例化场景 **********
        // 场景
        $sceList = array_keys($model->scenarios());
        if ($scenario && !empty($scenario) && in_array($scenario, $sceList)) {
            $model->setScenario($scenario);
        }

        return $model;
    }

    /**
     *  赋值数据库实例
     * @param AdminRoleDBModel|bool $dbModel
     * @return $this
     */
    public function setDbInstance($dbModel = false)
    {

        if (!$dbModel) {
            $this->dbInstance = AdminRoleDBModel::loadModel();
        } else {
            $this->dbInstance = $dbModel;
        }
        return $this;
    }

    /**
     * 获取全部列表
     * @param $page
     * @param $limit
     * @return array|\yii\db\ActiveRecord[]
     */
    public function getList($page, $limit)
    {

        // 条件
        $where = $this->where;

        // 当前页面计算
        $page = (($page - 1) < 0 ? 0 : ($page - 1));

        // 基础 where加载完毕
        $base = $this::find()->where($where);

        // 数据的获取 分页等
        $list = $base->offset($page * $limit)
            ->limit($limit)
            ->asArray()->all();

        $dbInstance = $this->dbInstance;
        // 格式化数据
        foreach ($list as $k => &$v) {

            // 更新时间
            if (!empty($v['update_time'])) {
                $v['update_time_text'] = date('Y-m-d H:i:s', $v['update_time']);
                $v['update_time_text_s'] = date('Y-m-d', $v['update_time']);
            }

            // 状态文本
            if (isset($v['status'])) {
                $v['status_text'] = $dbInstance::getStatusText($v['status']);
            }

            // 内容转化下
            if (!empty($v['content'])) {
                $v['content'] = htmlspecialchars_decode($v['content']);
                $v['content'] = CommonModel::addHtmlImgHost($v['content']);
            }
        }

        return $list;
    }

    /**
     * 加载条件
     * @param $where
     * @return $this
     */
    public function loadWhere($where)
    {

        // 条件不存在
        if (empty($where)) {

            return $this;
        }

        // 如果[where][0]是'and' 直接赋值
        $canRetList = ['and', 'or', 'AND', 'OR'];
        if (!empty($where[0]) && in_array($where[0], $canRetList)) {

            $this->where = $where;
            return $this;
        }

        // 不是数组 字符直接 判断
        if (!is_array($where)) {

            // 条件是 有效
            if (!empty($where) && $this->hasAttribute($where))

                $this->where = $where;

            // 条件 无有效
            return $this;
        }

        // 循环  条件是否有效
        $stagingWhere = [];
        foreach ($where as $k => $v) {

            // 首先值是有的，不能是空
            if ($v && is_array($v) && count($v) > 0 && $this->hasAttribute($k)) {

                $stagingWhere[] = ['IN', $k, array_values($v)];
                continue;
            }

            // 首先值是有的，不能是空
            if ($v && $this->hasAttribute($k)) {
                $stagingWhere[] = ['IN', $k, $v];
            }

        }

        // 条件最终赋值
        if (!empty($stagingWhere)) {
            $this->where = array_merge(['AND'], $stagingWhere);
        }

        return $this;
    }

    /**
     * 获取记录总数量
     * @return int|string
     */
    public function getCount()
    {

        // 条件
        $where = $this->where;

        // 基础 where加载完毕
        $count = $this::find()->where($where)->count();

        return $count;
    }

    /**
     * 添加|保存
     * @return bool
     */
    public function saveData()
    {

        $nowTime = time();

        // 添加的话要赋值一些初始数据
        if (empty($this->id)) {

            // 可以是走[mongoId]
            $this->id = CommonModel::newMongoId();
        }

        // 添加时间
        $this->update_time = $nowTime;

        // 内容不为空
        if (!empty($this->content)) {
            // 内容加密下
            $this->content = htmlspecialchars($this->content);
            // 内容取出图片域名
            $this->content = CommonModel::removeHtmlImgHost($this->content);
        }

        // [权限]是数组
        if (is_array($this->auth)) {
            $this->auth = json_encode($this->auth, JSON_UNESCAPED_UNICODE);
        }

        // [菜单]是数组
        if (is_array($this->menu)) {
            $this->menu = json_encode($this->menu, JSON_UNESCAPED_UNICODE);
        }

        if ($this->hasErrors() || !$this->validate() || !$this->save()) {

            return false;
        }

        return true;
    }

    /**
     * 获取当前角色[权限路由]列表
     */
    public function getAuthRoteList() {
        $auth = $this->getAttribute('auth');
        $auth = json_decode($auth, true);
        if (empty($auth)) return [];
        return array_column($auth, 'route');
    }


    /**
     * 更新某些字段
     * @param $condition
     * @param array $fieldVal
     * @return bool
     */
    public static function updateField($condition, $fieldVal = [])
    {

        $model = new self();
        foreach ($fieldVal as $k => $v) {

            if (!$model->hasAttribute($k)) {

                unset($fieldVal[$k]);
                continue;
            }
        }

        try {

            // ********** 1、首先更新下缓存数据 **********
            $model::updateAll($fieldVal, $condition);

            // ********** 2、将缓存中不存在的数据库条目同步 **********
            // 取出数据库条目
            $dbList = AdminRoleDBModel::find()->where($condition)->asArray()->all();
            // 数据库为空的直接为更新成功
            if (!$dbList) return true;
            // 取出数据库编号
            $dbIdList = array_column($dbList, 'id');

            // 取出缓存条目
            $cacheList = self::find()->where($condition)->asArray()->all();
            // 取出缓存编号
            $cacheIdList = array_column($cacheList, 'id');

            // 数据库为主取出差集
            $diffIdList = $dbIdList;
            if (!empty($cacheIdList)) {
                $diffIdList = array_diff($dbIdList, $cacheIdList);
            }
            // 此时不同编号为空返回下
            if (empty($diffIdList)) return true;

            $dbList = array_column($dbList, null, 'id');
            foreach ($diffIdList as $k => $v) {
                if (empty($dbList[$v])) continue;
                $model = new self();
                $model->setAttributes($dbList[$v]);
                $model->saveData();
            }

            return true;
        } catch (\Exception $error) {

            // 记录下错误日志
            \Yii::error([

                "``````````````````````````````````````````````````````````",
                "``                       缓存错误                         ``",
                "`` 错误详情: [后台角色操作模型]缓存中修改[指定字段]失败``",
                "`` {$error->getMessage()}                                 ``",
                "`` 错误信息和参数详情:                                     ``",
                "`````````````````````````````````````````````````````````",
                $error->getTraceAsString()
            ], 'normal');

            self::$error_ = empty($error->errorInfo) ?
                $error->getMessage() :
                implode(' | ', $error->errorInfo);

            return false;
        }
    }

    /**
     * 获取静态错误
     * @return mixed
     */
    public static function getStaticErrors()
    {
        return self::$error_;
    }

}
